// 虚拟列表核心Hook实现

import { useState, useRef, useCallback, useMemo, useEffect } from 'react';
import { 
  VirtualItem, 
  VirtualListState, 
  UseVirtualListReturn, 
  SizeCache,
  ScrollAlignment,
  VIRTUAL_LIST_DEFAULTS 
} from './types';

export interface UseVirtualListOptions {
  itemCount: number;
  containerHeight: number;
  itemHeight: number | ((index: number) => number);
  overscan?: number;
  scrollThrottleMs?: number;
  enableVirtualization?: boolean;
}

export function useVirtualList(options: UseVirtualListOptions): UseVirtualListReturn {
  const {
    itemCount,
    containerHeight,
    itemHeight,
    overscan = VIRTUAL_LIST_DEFAULTS.OVERSCAN,
    scrollThrottleMs = VIRTUAL_LIST_DEFAULTS.SCROLL_THROTTLE_MS,
    enableVirtualization = VIRTUAL_LIST_DEFAULTS.ENABLE_VIRTUALIZATION
  } = options;

  const containerRef = useRef<HTMLDivElement>(null);
  const scrollElementRef = useRef<HTMLDivElement>(null);
  const sizeCache = useRef<SizeCache>({});
  const scrollTimeoutRef = useRef<NodeJS.Timeout>();

  // 虚拟列表状态
  const [state, setState] = useState<VirtualListState>({
    scrollTop: 0,
    containerHeight,
    isScrolling: false,
    lastScrollTime: 0
  });

  // 获取项目高度
  const getItemSize = useCallback((index: number): number => {
    if (sizeCache.current[index] !== undefined) {
      return sizeCache.current[index];
    }

    const size = typeof itemHeight === 'function' ? itemHeight(index) : itemHeight;
    sizeCache.current[index] = size;
    return size;
  }, [itemHeight]);

  // 计算项目偏移量
  const getItemOffset = useCallback((index: number): number => {
    let offset = 0;
    for (let i = 0; i < index; i++) {
      offset += getItemSize(i);
    }
    return offset;
  }, [getItemSize]);

  // 计算总高度
  const totalSize = useMemo(() => {
    if (!enableVirtualization || itemCount < VIRTUAL_LIST_DEFAULTS.MIN_ITEMS_FOR_VIRTUALIZATION) {
      return itemCount * (typeof itemHeight === 'number' ? itemHeight : VIRTUAL_LIST_DEFAULTS.ITEM_HEIGHT);
    }

    let total = 0;
    for (let i = 0; i < itemCount; i++) {
      total += getItemSize(i);
    }
    return total;
  }, [itemCount, itemHeight, getItemSize, enableVirtualization]);

  // 计算可见范围
  const getVisibleRange = useCallback(() => {
    if (!enableVirtualization || itemCount < VIRTUAL_LIST_DEFAULTS.MIN_ITEMS_FOR_VIRTUALIZATION) {
      return {
        startIndex: 0,
        endIndex: itemCount - 1
      };
    }

    const { scrollTop, containerHeight } = state;
    let startIndex = 0;
    let endIndex = itemCount - 1;

    // 找到第一个可见项目
    let accumulatedHeight = 0;
    for (let i = 0; i < itemCount; i++) {
      const itemSize = getItemSize(i);
      if (accumulatedHeight + itemSize > scrollTop) {
        startIndex = i;
        break;
      }
      accumulatedHeight += itemSize;
    }

    // 找到最后一个可见项目
    accumulatedHeight = getItemOffset(startIndex);
    for (let i = startIndex; i < itemCount; i++) {
      if (accumulatedHeight > scrollTop + containerHeight) {
        endIndex = i - 1;
        break;
      }
      accumulatedHeight += getItemSize(i);
    }

    // 应用overscan
    startIndex = Math.max(0, startIndex - overscan);
    endIndex = Math.min(itemCount - 1, endIndex + overscan);

    return { startIndex, endIndex };
  }, [state, itemCount, getItemSize, getItemOffset, overscan, enableVirtualization]);

  // 计算虚拟项目
  const virtualItems = useMemo((): VirtualItem[] => {
    const { startIndex, endIndex } = getVisibleRange();
    const items: VirtualItem[] = [];

    for (let i = startIndex; i <= endIndex; i++) {
      const start = getItemOffset(i);
      const size = getItemSize(i);
      items.push({
        index: i,
        start,
        end: start + size,
        size
      });
    }

    return items;
  }, [getVisibleRange, getItemOffset, getItemSize]);

  // 滚动处理函数
  const handleScroll = useCallback((event: Event) => {
    const target = event.target as HTMLDivElement;
    const scrollTop = target.scrollTop;
    const now = Date.now();

    setState(prev => ({
      ...prev,
      scrollTop,
      isScrolling: true,
      lastScrollTime: now
    }));

    // 清除之前的超时
    if (scrollTimeoutRef.current) {
      clearTimeout(scrollTimeoutRef.current);
    }

    // 设置滚动结束标志
    scrollTimeoutRef.current = setTimeout(() => {
      setState(prev => ({
        ...prev,
        isScrolling: false
      }));
    }, scrollThrottleMs + 50);
  }, [scrollThrottleMs]);

  // 节流的滚动处理
  const throttledHandleScroll = useMemo(() => {
    let lastCall = 0;
    return (event: Event) => {
      const now = Date.now();
      if (now - lastCall >= scrollThrottleMs) {
        lastCall = now;
        handleScroll(event);
      }
    };
  }, [handleScroll, scrollThrottleMs]);

  // 滚动到指定索引
  const scrollToIndex = useCallback((index: number, align: ScrollAlignment = 'auto') => {
    if (!scrollElementRef.current || index < 0 || index >= itemCount) {
      return;
    }

    const itemOffset = getItemOffset(index);
    const itemSize = getItemSize(index);
    const { scrollTop } = state;

    let targetScrollTop = scrollTop;

    switch (align) {
      case 'start':
        targetScrollTop = itemOffset;
        break;
      case 'end':
        targetScrollTop = itemOffset + itemSize - containerHeight;
        break;
      case 'center':
        targetScrollTop = itemOffset + itemSize / 2 - containerHeight / 2;
        break;
      case 'auto':
        if (itemOffset < scrollTop) {
          // 项目在可见区域上方
          targetScrollTop = itemOffset;
        } else if (itemOffset + itemSize > scrollTop + containerHeight) {
          // 项目在可见区域下方
          targetScrollTop = itemOffset + itemSize - containerHeight;
        }
        // 项目已经可见，不需要滚动
        break;
    }

    // 限制滚动范围
    targetScrollTop = Math.max(0, Math.min(totalSize - containerHeight, targetScrollTop));

    scrollElementRef.current.scrollTo({
      top: targetScrollTop,
      behavior: 'smooth'
    });
  }, [getItemOffset, getItemSize, itemCount, state, containerHeight, totalSize]);

  // 滚动到指定偏移量
  const scrollToOffset = useCallback((offset: number) => {
    if (!scrollElementRef.current) {
      return;
    }

    const targetScrollTop = Math.max(0, Math.min(totalSize - containerHeight, offset));
    scrollElementRef.current.scrollTo({
      top: targetScrollTop,
      behavior: 'smooth'
    });
  }, [totalSize, containerHeight]);

  // 监听容器高度变化
  useEffect(() => {
    setState(prev => ({
      ...prev,
      containerHeight
    }));
  }, [containerHeight]);

  // 绑定滚动事件
  useEffect(() => {
    const scrollElement = scrollElementRef.current;
    if (!scrollElement) {
      return;
    }

    scrollElement.addEventListener('scroll', throttledHandleScroll, { passive: true });

    return () => {
      scrollElement.removeEventListener('scroll', throttledHandleScroll);
      if (scrollTimeoutRef.current) {
        clearTimeout(scrollTimeoutRef.current);
      }
    };
  }, [throttledHandleScroll]);

  // 清理缓存
  useEffect(() => {
    sizeCache.current = {};
  }, [itemHeight, itemCount]);

  const { startIndex, endIndex } = getVisibleRange();

  return {
    virtualItems,
    totalSize,
    startIndex,
    endIndex,
    scrollToIndex,
    scrollToOffset,
    containerRef: scrollElementRef
  };
}

// 导出辅助函数
export const virtualListUtils = {
  // 计算渲染比例
  calculateRenderRatio: (totalItems: number, renderedItems: number): number => {
    return totalItems > 0 ? renderedItems / totalItems : 0;
  },

  // 获取性能指标
  getPerformanceMetrics: (
    totalItems: number,
    renderedItems: number,
    isVirtualized: boolean,
    scrollPosition: number,
    averageItemHeight: number
  ) => ({
    totalItems,
    renderedItems,
    renderRatio: virtualListUtils.calculateRenderRatio(totalItems, renderedItems),
    averageItemHeight,
    scrollPosition,
    isVirtualized
  })
};